home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / GIFLIB12.ARJ / GIF2PS.C < prev    next >
C/C++ Source or Header  |  1991-05-12  |  12KB  |  388 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Jul. 1989   *
  5. ******************************************************************************
  6. * Program to dump GIF file into PostScript type printers             *
  7. * Options:                                     *
  8. * -q : quite printing mode.                             *
  9. * -x : force image to be horizontal.                         *
  10. * -y : force image to be vertical.                         *
  11. * -s x y : force image to be of given size.                     *
  12. * -p x y : force image to be positioned at given position in page.         *
  13. * -i : invert the image.                             *
  14. * -n n : number of copies.                             *
  15. * -h : on line help.                                 *
  16. ******************************************************************************
  17. * History:                                     *
  18. * 22 Dec 89 - Version 1.0 by Gershon Elber.                     *
  19. *****************************************************************************/
  20.  
  21. #ifdef __MSDOS__
  22. #include <graphics.h>
  23. #include <stdlib.h>
  24. #include <alloc.h>
  25. #include <io.h>
  26. #include <dos.h>
  27. #include <bios.h>
  28. #endif /* __MSDOS__ */
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <string.h>
  33. #include <fcntl.h>
  34. #include "gif_lib.h"
  35. #include "getarg.h"
  36.  
  37. #define PROGRAM_NAME    "Gif2PS"
  38.  
  39. #define PAGE_WIDTH      7.5            /* All dimensions are in inches. */
  40. #define PAGE_HEIGHT     9.0
  41. #define FULL_PAGE_WIDTH 8.5
  42. #define FULL_PAGE_HEIGHT 11.0
  43.  
  44. #define UNKNOWN_ORIENT        0
  45. #define HORIZONTAL_ORIENT    1 
  46. #define VERTICAL_ORIENT        2
  47.  
  48. #ifdef __MSDOS__
  49. extern unsigned int
  50.     _stklen = 16384;                 /* Increase default stack size. */
  51. #endif /* __MSDOS__ */
  52.  
  53. #ifdef SYSV
  54. static char *VersionStr =
  55.         "Gif library module,\t\tGershon Elber\n\
  56.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  57. static char
  58.     *CtrlStr = "Gif2PS q%- x%- y%- s%-SizeX|SizeY!F!F p%-PosX|PosY!F!F i%- n%-#Copies!d h%- GifFile!*s";
  59. #else
  60. static char
  61.     *VersionStr =
  62.     PROGRAM_NAME
  63.     GIF_LIB_VERSION
  64.     "    Gershon Elber,    "
  65.     __DATE__ ",   " __TIME__ "\n"
  66.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  67. static char
  68.     *CtrlStr =
  69.     PROGRAM_NAME
  70.     " q%- x%- y%- s%-SizeX|SizeY!F!F p%-PosX|PosY!F!F i%- n%-#Copies!d h%- GifFile!*s";
  71. #endif /* SYSV */
  72.  
  73. /* Make some variables global, so we could access them faster: */
  74. static int
  75.     ImageNum = 0,
  76.     BackGround = 0,
  77.     ForceXFlag = FALSE,
  78.     ForceYFlag = FALSE,
  79.     SizeFlag = FALSE,
  80.     PosFlag = FALSE,
  81.     InvertFlag = FALSE,
  82.     NumCopiesFlag = FALSE,
  83.     HelpFlag = FALSE,
  84.     NumOfCopies = 1,
  85.     InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
  86.     InterlacedJumps[] = { 8, 8, 4, 2 },    /* be read - offsets and jumps... */
  87.     PSOrientation;
  88. static double PSSizeX, PSSizeY, PSPosX, PSPosY;
  89. static GifColorType
  90.     *ColorMap;
  91.  
  92. static void DumpScreen2PS(GifRowType *ScreenBuffer,
  93.                     int ScreenWidth, int ScreenHeight);
  94. static void PutString(unsigned char *Line, int Len);
  95.  
  96. /******************************************************************************
  97. * Interpret the command line and scan the given GIF file.              *
  98. ******************************************************************************/
  99. void main(int argc, char **argv)
  100. {
  101.     int    i, j, Error, NumFiles, Size, Row, Col, Width, Height, ExtCode, Count;
  102.     GifRecordType RecordType;
  103.     GifByteType *Extension;
  104.     char **FileName = NULL;
  105.     GifRowType *ScreenBuffer;
  106.     GifFileType *GifFile;
  107.  
  108.     if ((Error = GAGetArgs(argc, argv, CtrlStr,&GifQuitePrint,
  109.         &ForceXFlag, &ForceYFlag, &SizeFlag, &PSSizeX, &PSSizeY,
  110.         &PosFlag, &PSPosX, &PSPosY,
  111.         &InvertFlag, &NumCopiesFlag, &NumOfCopies, &HelpFlag,
  112.         &NumFiles, &FileName)) != FALSE ||
  113.         (NumFiles > 1 && !HelpFlag)) {
  114.     if (Error)
  115.         GAPrintErrMsg(Error);
  116.     else if (NumFiles > 1)
  117.         GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  118.     GAPrintHowTo(CtrlStr);
  119.     exit(1);
  120.     }
  121.  
  122.     if (HelpFlag) {
  123.     fprintf(stderr, VersionStr);
  124.     GAPrintHowTo(CtrlStr);
  125.     exit(0);
  126.     }
  127.  
  128.     if (ForceXFlag)
  129.         PSOrientation = HORIZONTAL_ORIENT;
  130.     else if (ForceYFlag)
  131.         PSOrientation = VERTICAL_ORIENT;
  132.     else
  133.     PSOrientation = UNKNOWN_ORIENT;
  134.  
  135.     if (NumFiles == 1) {
  136.     if ((GifFile = DGifOpenFileName(*FileName)) == NULL) {
  137.         PrintGifError();
  138.         exit(-1);
  139.     }
  140.     }
  141.     else {
  142.     /* Use the stdin instead: */
  143.  
  144. #ifdef __MSDOS__
  145.     setmode(0, O_BINARY);
  146. #endif /* __MSDOS__ */
  147.     if ((GifFile = DGifOpenFileHandle(0)) == NULL) {
  148.         PrintGifError();
  149.         exit(-1);
  150.     }
  151.     }
  152.  
  153.     /* Allocate the screen as vector of column of rows. We cannt allocate    */
  154.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  155.     /* 64k at a time and our image can be bigger than that:             */
  156.     /* Note this screen is device independent - its the screen as defined by */
  157.     /* the GIF file parameters itself.                         */
  158.     if ((ScreenBuffer = (GifRowType *)
  159.     malloc(GifFile -> SHeight * sizeof(GifRowType *))) == NULL)
  160.         GIF_EXIT("Failed to allocate memory required, aborted.");
  161.  
  162.     Size = GifFile -> SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/
  163.     if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */
  164.     GIF_EXIT("Failed to allocate memory required, aborted.");
  165.  
  166.     for (i = 0; i < GifFile -> SWidth; i++) /* Set its color to BackGround. */
  167.     ScreenBuffer[0][i] = GifFile -> SBackGroundColor;
  168.     for (i = 1; i < GifFile -> SHeight; i++) {
  169.     /* Allocate the other rows, and set their color to background too:  */
  170.     if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL)
  171.         GIF_EXIT("Failed to allocate memory required, aborted.");
  172.  
  173.     memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
  174.     }
  175.  
  176.     /* Scan the content of the GIF file and load the image(s) in: */
  177.     do {
  178.     if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
  179.         PrintGifError();
  180.         exit(-1);
  181.     }
  182.     switch (RecordType) {
  183.         case IMAGE_DESC_RECORD_TYPE:
  184.         if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
  185.             PrintGifError();
  186.             exit(-1);
  187.         }
  188.         Row = GifFile -> ITop; /* Image Position relative to Screen. */
  189.         Col = GifFile -> ILeft;
  190.         Width = GifFile -> IWidth;
  191.         Height = GifFile -> IHeight;
  192.         GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  193.             PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height);
  194.         if (GifFile -> ILeft + GifFile -> IWidth > GifFile -> SWidth ||
  195.            GifFile -> ITop + GifFile -> IHeight > GifFile -> SHeight) {
  196.             fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n");
  197.             exit(-2);
  198.         }
  199.         if (GifFile -> IInterlace) {
  200.             /* Need to perform 4 passes on the images: */
  201.              for (Count = i = 0; i < 4; i++)
  202.             for (j = Row + InterlacedOffset[i]; j < Row + Height;
  203.                          j += InterlacedJumps[i]) {
  204.                 GifQprintf("\b\b\b\b%-4d", Count++);
  205.                 if (DGifGetLine(GifFile, &ScreenBuffer[j][Col],
  206.                 Width) == GIF_ERROR) {
  207.                 PrintGifError();
  208.                 exit(-1);
  209.                 }
  210.             }
  211.         }
  212.         else {
  213.             for (i = 0; i < Height; i++) {
  214.             GifQprintf("\b\b\b\b%-4d", i);
  215.             if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],
  216.                 Width) == GIF_ERROR) {
  217.                 PrintGifError();
  218.                 exit(-1);
  219.             }
  220.             }
  221.         }
  222.         break;
  223.         case EXTENSION_RECORD_TYPE:
  224.         /* Skip any extension blocks in file: */
  225.         if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
  226.             PrintGifError();
  227.             exit(-1);
  228.         }
  229.         while (Extension != NULL) {
  230.             if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
  231.             PrintGifError();
  232.             exit(-1);
  233.             }
  234.         }
  235.         break;
  236.         case TERMINATE_RECORD_TYPE:
  237.         break;
  238.         default:            /* Should be traps by DGifGetRecordType. */
  239.         break;
  240.     }
  241.     }
  242.     while (RecordType != TERMINATE_RECORD_TYPE);
  243.  
  244.     /* Lets display it - set the global variables required and do it: */
  245.     BackGround = GifFile -> SBackGroundColor;
  246.     ColorMap = (GifFile -> IColorMap ? GifFile -> IColorMap :
  247.                        GifFile -> SColorMap);
  248.     DumpScreen2PS(ScreenBuffer, GifFile -> SWidth, GifFile -> SHeight);
  249.  
  250.     if (DGifCloseFile(GifFile) == GIF_ERROR) {
  251.     PrintGifError();
  252.     exit(-1);
  253.     }
  254. }
  255.  
  256. /******************************************************************************
  257. * The real dumping routine.                              *
  258. ******************************************************************************/
  259. static void DumpScreen2PS(GifRowType *ScreenBuffer,
  260.                     int ScreenWidth, int ScreenHeight)
  261. {
  262.     int i, j;
  263.     double Aspect;
  264.     GifByteType *OutLine, Data;
  265.     GifPixelType *Line;
  266.     GifColorType *ColorMapEntry;
  267.  
  268.     /* If user did not enforce orientation, pick the best one. */
  269.     if (PSOrientation == UNKNOWN_ORIENT)
  270.     if (ScreenWidth > ScreenHeight)
  271.         PSOrientation = VERTICAL_ORIENT;
  272.     else
  273.         PSOrientation = HORIZONTAL_ORIENT;
  274.  
  275.     Aspect = ((double) ScreenHeight) / ((double) ScreenWidth);
  276.  
  277.     if (!SizeFlag)
  278.     switch (PSOrientation) {
  279.             case HORIZONTAL_ORIENT:
  280.             if (Aspect > PAGE_HEIGHT / PAGE_WIDTH) {
  281.             PSSizeX = PAGE_HEIGHT / Aspect; 
  282.             PSSizeY = PAGE_HEIGHT;
  283.         }
  284.         else {
  285.             PSSizeX = PAGE_WIDTH;
  286.             PSSizeY = PAGE_WIDTH * Aspect;
  287.         }
  288.         break;
  289.         case VERTICAL_ORIENT:
  290.             if (1 / Aspect > PAGE_HEIGHT / PAGE_WIDTH) {
  291.             PSSizeX = PAGE_HEIGHT * Aspect; 
  292.             PSSizeY = PAGE_HEIGHT;
  293.         }
  294.         else {
  295.             PSSizeX = PAGE_WIDTH;
  296.             PSSizeY = PAGE_WIDTH / Aspect;
  297.         }
  298.         break;
  299.     }
  300.     else {
  301.     if (PAGE_WIDTH < PSSizeX) {
  302.         GIF_MESSAGE("X Size specified is too big, page size selected.");
  303.         PSSizeX = PAGE_WIDTH;
  304.     }
  305.     if (PAGE_HEIGHT < PSSizeY) {
  306.         GIF_MESSAGE("Y Size specified is too big, page size selected.");
  307.         PSSizeX = PAGE_HEIGHT;
  308.     }
  309.     }
  310.  
  311.     if (!PosFlag) {
  312.     PSPosX = (FULL_PAGE_WIDTH - PSSizeX) / 2;
  313.     PSPosY = (FULL_PAGE_HEIGHT - PSSizeY) / 2;
  314.     }
  315.     else {
  316.     if (PSPosX + PSSizeX > PAGE_WIDTH || PSPosY + PSSizeY > PAGE_HEIGHT)
  317.         GIF_EXIT("Requested position will put image out of page, aborted.");
  318.     }
  319.  
  320.     /* Time to dump out the PostScript header: */
  321.     printf("%%!\n");
  322.     printf("%%%%Creator: %s\n", PROGRAM_NAME);
  323.     printf("/#copies %d def\n", NumOfCopies);
  324.     printf("gsave\n");
  325.     printf("72 72 scale\t\t\t\t%% Lets talk inches.\n");
  326.     printf("/oneline %d string def\t\t\t%% Allocate one scan line.\n",
  327.        ScreenWidth);
  328.     printf("/drawimage {\n");
  329.     printf("\t%d %d 8 [%d 0 0 %d 0 %d]\n", ScreenWidth, ScreenHeight,
  330.        ScreenWidth, -ScreenHeight, ScreenHeight);
  331.     printf("\t{ currentfile oneline readhexstring pop } image\n");
  332.     printf("} def\n");
  333.     switch (PSOrientation) {
  334.         case HORIZONTAL_ORIENT:
  335.         printf("%lf %lf translate\n", PSPosX, PSPosY);
  336.         printf("%lf %lf scale\n", PSSizeX, PSSizeY);
  337.         break;
  338.     case VERTICAL_ORIENT:
  339.         printf("%lf %lf translate\n", PSPosX + PSSizeX, PSPosY);
  340.         printf("90 rotate\n");
  341.         printf("%lf %lf scale\n", PSSizeY, PSSizeX);
  342.         break;
  343.     }
  344.     printf("drawimage\n");
  345.  
  346.     if ((OutLine = (GifByteType *) malloc(sizeof(GifByteType) * ScreenWidth))
  347.                                 == NULL)
  348.     GIF_EXIT("Failed to allocate memory required, aborted.");
  349.  
  350.     for (i = 0; i < ScreenHeight; i++) {
  351.     GifQprintf("\b\b\b\b%-4d", ScreenHeight - i);
  352.  
  353.     Line = ScreenBuffer[i];
  354.     for (j = 0; j < ScreenWidth; j++) {
  355.         ColorMapEntry = &ColorMap[Line[j]];
  356.         Data = (30 * ((unsigned int) ColorMapEntry->Red) +
  357.             59 * ((unsigned int) ColorMapEntry->Green) +
  358.             11 * ((unsigned int) ColorMapEntry->Blue)) / 100;
  359.         OutLine[j] = InvertFlag ? 255 - Data : Data;
  360.     }
  361.  
  362.     PutString(OutLine, ScreenWidth);
  363.     }
  364.     free(OutLine);
  365.  
  366.     printf("\nshowpage\n");
  367.     printf("grestore\n");
  368. }
  369.  
  370. /******************************************************************************
  371. * Dumps the string of given length as 2 hexdigits per byte 39 bytes per line. *
  372. ******************************************************************************/
  373. static void PutString(unsigned char *Line, int Len)
  374. {
  375.     int i;
  376.     static Counter = 0;
  377.     static char *Hex = "0123456789ABCDEF";
  378.  
  379.     for (i = 0; i < Len; i++) {
  380.     if (++Counter % 40 == 0) {
  381.         putchar('\n');
  382.         Counter = 1;
  383.     }
  384.     putchar(Hex[Line[i] >> 4]);
  385.     putchar(Hex[Line[i] & 0x0f]);
  386.     }
  387. }
  388.